/**
This file is part of Gel2DE.

    Gel2DE is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Gel2DE is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Gel2DE.  If not, see <http://www.gnu.org/licenses/>.

	Copyright (C) 2012, University of Bergen
*/

#include "ResultImageViewer.h"
#include "vtkImageCanvasSource2D.h"
#include "vtkImageMapper.h"

ResultImageViewer::ResultImageViewer(vtkRenderWindowInteractor* aInteractor, 
									 char* aPath, 
									 GelImageViewer* aViewer, 
									 vtkColorTransferFunction * ctf)
{
	m_ctf = NULL;
	m_renderWindowInteractor = aInteractor;
	m_gelImageViewer = aViewer;
	m_path = aPath;
	m_gelCorrelationAnalysis = NULL;
	m_ctf = ctf;

	m_buttonDown = FALSE;

	ConstructVTK();
	ListenToGelImageInteractor();
	SetupMouseListener();
}

ResultImageViewer::~ResultImageViewer(void)
{
	m_actor->Delete();
	m_renderer->Delete();
}

void ResultImageViewer::SetGelCorrelationAnalysis(GelCorrelationAnalysis* aGelCorrelationAnalysis)
{
	m_gelCorrelationAnalysis = aGelCorrelationAnalysis;
}


void ResultImageViewer::Render()
{
	if(m_Cconnector->GetOutput() != NULL)
	{
		m_renderWindowInteractor->Render();
	}
}

void ResultImageViewer::Clear()
{
	m_actor->VisibilityOff();
	m_rectangleActor->VisibilityOff();
}

void ResultImageViewer::UpdateConnectors()
{
	m_Cconnector->Update();
	m_Sconnector->Update();
	m_CSconnector->Update();
	m_CSDconnector->Update();
	m_Pconnector->Update();
	m_PTconnector->Update();
	m_Dconnector->Update();
}

void ResultImageViewer::Update()
{
	m_actor->VisibilityOn();
	UpdateConnectors();
	AnalyzeROI();
	m_renderWindowInteractor->Render();
}	

void ResultImageViewer::DisplayElement(int aElement)
{
	if(aElement == 0)
	{
		m_imageMapToColors->SetInput(m_Cconnector->GetOutput());
	}
	if(aElement == 1)
	{
		m_imageMapToColors->SetInput(m_CSconnector->GetOutput());
	}
	if(aElement == 2)
	{
		m_imageMapToColors->SetInput(m_CSDconnector->GetOutput());
	}
	if(aElement == 3)
	{
		m_imageMapToColors->SetInput(m_Sconnector->GetOutput());
	}
	if(aElement == 4)
	{
		m_imageMapToColors->SetInput(m_Dconnector->GetOutput());
	}
	if(aElement == 5)
	{
		m_imageMapToColors->SetInput(m_Pconnector->GetOutput());
	}
	if(aElement == 6)
	{
		m_imageMapToColors->SetInput(m_PTconnector->GetOutput());
		//This is to force update after cumulative PT calculation. 
		//Should be put a better place...
		m_PTconnector->Modified();
		m_imageMapToColors->Modified();
	}
}

void ResultImageViewer::ConstructVTK()
{

	m_Cconnector = ConnectorType::New();
	m_Sconnector = ConnectorType::New();
	m_Pconnector = ConnectorType::New();
	m_PTconnector = ConnectorType::New();
	m_Dconnector = ConnectorType::New();
	m_CSconnector = ConnectorType::New();
	m_CSDconnector = ConnectorType::New();

	m_imageMapToColors = vtkImageMapToColors::New();

	m_imageMapToColors->SetLookupTable(m_ctf);
	m_imageMapToColors->SetInput(m_Cconnector->GetOutput());

	m_actor = vtkImageActor::New();
	m_actor->SetInput(m_imageMapToColors->GetOutput());
	m_actor->InterpolateOff();


	m_cursorTextActor = vtkTextActor::New();
	m_cursorTextActor->SetInput("Cursor\n");
	m_cursorTextActor->GetPositionCoordinate()->SetCoordinateSystemToNormalizedDisplay();
	m_cursorTextActor->GetPositionCoordinate()->SetValue(0.02, 0.02);
	m_cursorTextActor->GetTextProperty()->SetColor(0.,0.,0.);
	m_cursorTextActor->SetTextScaleModeToViewport();

	m_ROITextActor = vtkTextActor::New();
	m_ROITextActor->SetInput("ROI statistics:\nNo ROI selected");
	m_ROITextActor->GetPositionCoordinate()->SetCoordinateSystemToNormalizedDisplay();
	m_ROITextActor->GetPositionCoordinate()->SetValue(0.02, 0.85);
	m_ROITextActor->GetTextProperty()->SetColor(0.,0.,0.);
	m_ROITextActor->SetTextScaleModeToViewport();

	m_infoTextActor = vtkTextActor::New();
	SetMetaInfo("None", 0, 0.);
	m_infoTextActor->GetPositionCoordinate()->SetCoordinateSystemToNormalizedDisplay();
	m_infoTextActor->GetPositionCoordinate()->SetValue(0.5, 0.02);
	m_infoTextActor->GetTextProperty()->SetColor(0.,0.,0.);
	m_infoTextActor->SetTextScaleModeToViewport();


	//vtkInteractorStyleRubberBand2D *rubber = vtkInteractorStyleRubberBand2D::New();
	vtkInteractorStyleUser* interactorStyle = vtkInteractorStyleUser::New();
	

	m_colorBar = vtkScalarBarActor::New();

	m_colorBar->SetLookupTable(m_ctf);
	m_colorBar->SetMaximumNumberOfColors(1000);
	m_colorBar->GetLabelTextProperty()->ShadowOn();
	m_colorBar->GetLabelTextProperty()->ItalicOff();
	m_colorBar->SetWidth(0.1);
	m_colorBar->GetLabelTextProperty()->SetFontSize(5);
	m_colorBar->SetLabelFormat("%.1f");

	m_renderer = vtkRenderer::New();

	vtkImageCanvasSource2D *canvasSource = vtkImageCanvasSource2D::New();
	canvasSource->SetNumberOfScalarComponents(4);
	canvasSource->SetExtent(0, 300, 0, 50, 0, 0);
	canvasSource->SetDrawColor(200, 200, 200, 200);
	canvasSource->FillBox(0, 300, 0, 50);
	vtkActor2D *canvActor = vtkActor2D::New();
	vtkImageMapper *canvMapper = vtkImageMapper::New();
	canvMapper->SetInput(canvasSource->GetOutput());
	canvActor->SetMapper(canvMapper);

	//m_renderer->AddActor(canvActor);
	

	m_renderer->AddActor(m_actor);
	m_renderer->AddActor(m_colorBar);
	m_renderer->AddActor(m_cursorTextActor);
	m_renderer->AddActor(m_ROITextActor);
	m_renderer->AddActor(m_infoTextActor);

	m_actor->VisibilityOff();

	double col[3];
	col[0] = 0.5;
	col[1] = 0.5;
	col[2] = 0.5;
	m_renderer->SetBackground(col);

	//m_renderWindowInteractor->SetInteractorStyle(rubber);
	m_renderWindowInteractor->SetInteractorStyle(interactorStyle);
	m_renderWindowInteractor->GetRenderWindow()->AddRenderer(m_renderer);

	m_pointPicker = vtkPropPicker::New();

	m_renderWindowInteractor->SetPicker(m_pointPicker);

	InitializeRectangle();

	m_renderer->AddActor(m_rectangleActor);

	m_rectangleActor->VisibilityOff();

}

void ResultImageViewer::InitializeRectangle()
{
	m_rect = vtkPoints::New();
	m_rect->SetNumberOfPoints(4);

	m_rect->InsertPoint(0, 0, 0, 0);
	m_rect->InsertPoint(1, 0, 100, 0);
	m_rect->InsertPoint(2, 100, 100, 0);
	m_rect->InsertPoint(3, 100, 0, 0);

	vtkPolyData* rectanglePolyData = vtkPolyData::New();
	rectanglePolyData->SetPoints(m_rect);
	vtkCellArray* rect = vtkCellArray::New();
	rect->InsertNextCell(5);
	rect->InsertCellPoint(0);
	rect->InsertCellPoint(1);
	rect->InsertCellPoint(2);
	rect->InsertCellPoint(3);
	rect->InsertCellPoint(0);

	rectanglePolyData->SetLines(rect);
	vtkPolyDataMapper* rectangleMapper = vtkPolyDataMapper::New();
	rectangleMapper->SetInput(rectanglePolyData);
	m_rectangleActor = vtkActor::New();
	m_rectangleActor->SetMapper(rectangleMapper);
	m_rectangleActor->GetProperty()->SetColor(1., 0., 0.);
}


void gelImageUpdated(vtkObject *caller, unsigned long event, void* clientdata, void* callerdata)
{
	ResultImageViewer *viewer = (ResultImageViewer*)clientdata;
	viewer->UpdateCamera();
}

void mouseListener(vtkObject *caller, unsigned long event, void* clientdata, void* callerdata)
{
	ResultImageViewer* viewer = (ResultImageViewer*)clientdata;
	viewer->Event(event);
}

void ResultImageViewer::UpdateRectangle(vtkPoints* aPoints)
{
	for(int i = 0; i < aPoints->GetNumberOfPoints(); i++)
	{
		double point[3];
		aPoints->GetPoint(i, point);
		m_rect->InsertPoint(i, point);
	}
	m_rect->Modified();
	AnalyzeROI();
	m_renderWindowInteractor->Render();
}

void ResultImageViewer::SetRectangleVisible(int aVisible)
{
	m_rectangleActor->SetVisibility(aVisible);
}

int ResultImageViewer::HasResult()
{
	if(m_gelCorrelationAnalysis->getCImage())
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

void ResultImageViewer::Event(unsigned long event)
{

	int currentPos[2];
	m_renderWindowInteractor->GetEventPosition(currentPos);

	/*
	double pickPos[3];
	pickPos[0] = 0;
	pickPos[1] = 0;
	pickPos[2] = 0;
	*/

	m_pointPicker->Pick(currentPos[0], currentPos[1], 0, m_renderer);
	m_pointPicker->GetPickPosition(m_currentPos);
	vtkProp3D* actor = m_pointPicker->GetProp3D();

	if(actor != NULL)
	{
		m_currentPos[0] = m_currentPos[0] + 0.5;
		m_currentPos[1] = m_currentPos[1] + 0.5;
	}

	double error = 0.5;

	if(event == vtkCommand::LeftButtonPressEvent)
	{
		m_rectangleActor->VisibilityOn();
		m_buttonDownPosition[0] = m_currentPos[0];
		m_buttonDownPosition[1] = m_currentPos[1];
		m_buttonDownPosition[2] = m_currentPos[2];
		m_buttonDown = TRUE;

		m_rect->InsertPoint(0, floor(m_buttonDownPosition[0]), floor(m_buttonDownPosition[1]), m_buttonDownPosition[2] + 0.1);
		m_rect->InsertPoint(1, floor(m_buttonDownPosition[0]), floor(m_buttonDownPosition[1]), m_buttonDownPosition[2] + 0.1);
		m_rect->InsertPoint(2, floor(m_buttonDownPosition[0]), floor(m_buttonDownPosition[1]), m_buttonDownPosition[2] + 0.1);
		m_rect->InsertPoint(3, floor(m_buttonDownPosition[0]), floor(m_buttonDownPosition[1]), m_buttonDownPosition[2] + 0.1);
		m_rect->Modified();
		m_gelImageViewer->UpdateRectangle(m_rect);
		m_gelImageViewer->SetRectangleVisible(1);
	}

	if(event == vtkCommand::LeftButtonReleaseEvent)
	{
		m_buttonDown = FALSE;
		
		m_renderWindowInteractor->Render();


	}

	if(event == vtkCommand::RightButtonReleaseEvent)
	{
		HideRectangle();
		m_renderWindowInteractor->Render();
	}

	if(event == vtkCommand::MouseMoveEvent)
	{
		double Cvalue = 0;
		double Svalue = 0;
		double Pvalue = 0;
		double PTvalue = 0;
		double Dvalue = 0;


		vtkImageActor* imageactor = (vtkImageActor*)actor;
		if(imageactor)
		{
			GelCorrelationAnalysis::DataImageType::SizeType maxRegion = m_gelCorrelationAnalysis->getCImage()->GetLargestPossibleRegion().GetSize();
//Check if it is inside the region, due to hack to get ITK/VTK mismatch invisible...
			if((int)m_currentPos[0] >= 0 && (int)m_currentPos[0] < maxRegion[0] && (int)m_currentPos[1] >= 0 && (int)m_currentPos[1] < maxRegion[1])
			{

				Cvalue = m_Cconnector->GetOutput()->GetScalarComponentAsDouble((int)m_currentPos[0], (int)m_currentPos[1], (int)m_currentPos[2], 0);
				Svalue = m_Sconnector->GetOutput()->GetScalarComponentAsDouble((int)m_currentPos[0], (int)m_currentPos[1], (int)m_currentPos[2], 0);
				Pvalue = m_Pconnector->GetOutput()->GetScalarComponentAsDouble((int)m_currentPos[0], (int)m_currentPos[1], (int)m_currentPos[2], 0);
				PTvalue = m_PTconnector->GetOutput()->GetScalarComponentAsDouble((int)m_currentPos[0], (int)m_currentPos[1], (int)m_currentPos[2], 0);
				Dvalue = m_Dconnector->GetOutput()->GetScalarComponentAsDouble((int)m_currentPos[0], (int)m_currentPos[1], (int)m_currentPos[2], 0);
				if(m_buttonDown)
				{
					double buttonDownPos[2];
					double currentBoxPos[2];

					buttonDownPos[0] = floor(m_buttonDownPosition[0]) - 0.5;
					buttonDownPos[1] = floor(m_buttonDownPosition[1]) - 0.5;

					currentBoxPos[0] = floor(m_currentPos[0]) - 0.5;
					currentBoxPos[1] = floor(m_currentPos[1]) - 0.5;

					if(m_buttonDownPosition[0] < m_currentPos[0])
					{
						currentBoxPos[0] += 1;
					}
					else
					{
						buttonDownPos[0] += 1;
					}

					if(m_buttonDownPosition[1] < m_currentPos[1])
					{
						currentBoxPos[1] += 1;
					}
					else
					{
						buttonDownPos[1] += 1;
					}
					SetRoi(buttonDownPos[0], buttonDownPos[1], m_buttonDownPosition[2],
						currentBoxPos[0], currentBoxPos[1], m_buttonDownPosition[2]);
/*
					m_rect->InsertPoint(0, buttonDownPos[0], buttonDownPos[1], m_buttonDownPosition[2] + 0.1);
					m_rect->InsertPoint(1, currentBoxPos[0], buttonDownPos[1], m_buttonDownPosition[2] + 0.1);
					m_rect->InsertPoint(2, currentBoxPos[0], currentBoxPos[1], m_buttonDownPosition[2] + 0.1);
					m_rect->InsertPoint(3, buttonDownPos[0], currentBoxPos[1], m_buttonDownPosition[2] + 0.1);
					m_rect->Modified();

					m_gelImageViewer->UpdateRectangle(m_rect);				

					AnalyzeROI();
					*/
				}
			}
		}



		char string[400];
		sprintf_s(string, "Position : %.2d %.2d\nC: %.2f P: %.2f PT: %.2f D: %.2f", (int)m_currentPos[0], (int)m_currentPos[1], Cvalue, Pvalue, PTvalue, Dvalue);
		m_cursorTextActor->SetInput(string);
		m_renderWindowInteractor->Render();
	}
}

void ResultImageViewer::SetRoi(int startx, int starty, int startz, int stopx, int stopy, int stopz)
{
	startz = m_buttonDownPosition[2];
	m_rect->InsertPoint(0, startx, starty,  startz + 0.1);
	m_rect->InsertPoint(1, stopx, starty, startz + 0.1);
	m_rect->InsertPoint(2, stopx, stopy, startz + 0.1);
	m_rect->InsertPoint(3, startx, stopy, startz + 0.1);
	m_rect->Modified();

	m_gelImageViewer->UpdateRectangle(m_rect);				

	m_rectangleActor->VisibilityOn();
	m_gelImageViewer->UpdateRectangle(m_rect);
	m_gelImageViewer->SetRectangleVisible(1);

	AnalyzeROI();
	m_renderWindowInteractor->Render();

}

void ResultImageViewer::HideRectangle()
{
	m_rectangleActor->VisibilityOff();
	m_gelImageViewer->SetRectangleVisible(0);
	m_ROITextActor->SetInput("ROI statistics:\nNo ROI selected");
}

void ResultImageViewer::UpdateCamera()
{
	vtkCamera *gelImageCamera = m_gelImageViewer->GetCamera();

	m_renderer->SetActiveCamera(gelImageCamera);
	m_renderer->Modified();
	m_renderWindowInteractor->Render();

}

void ResultImageViewer::GetROIDefinition(GelCorrelationAnalysis::DataImageType::RegionType* aRoiDefinition)
{
	GelCorrelationAnalysis::DataImageType::SizeType roiSize;
	GelCorrelationAnalysis::DataImageType::IndexType roiIndex;
	double p1[3];
	double p2[3];
	m_rect->GetPoint(0, p1);
	m_rect->GetPoint(2, p2);

	roiSize[0] = abs(p2[0] - p1[0]);
	roiSize[1] = abs(p2[1] - p1[1]);

	//The index has to be the smallest in each case
	if(p1[0] < p2[0]) roiIndex[0] = p1[0] + 1;
	else roiIndex[0] = p2[0] + 1;

	if(p1[1] < p2[1]) roiIndex[1] = p1[1] + 1;
	else roiIndex[1] = p2[1] + 1;

	//GelCorrelationAnalysis::DataImageType::RegionType roiDefinition;
	aRoiDefinition->SetIndex(roiIndex);
	aRoiDefinition->SetSize(roiSize);
	//return roiDefinition;
}

void ResultImageViewer::AnalyzeROI()
{
	//Here we also want to calculate max and min.
	//How is this best done? Probably by taking the itk image
	//defining in a region in this and iterating through it to find
	//the max and min values.
	//But, first we need the CS and CSD connectors as well.

	//Probably it would be nice to draw the marker also in the raw data image.
	//Should be doable, since we already know the coordinate systems are the same.
	//(no guarantee?)
	GelCorrelationAnalysis::DataImageType::Pointer cimage = m_gelCorrelationAnalysis->getCImage();
	GelCorrelationAnalysis::DataImageType::SizeType rawSize = cimage->GetRequestedRegion().GetSize();

	GelCorrelationAnalysis::DataImageType::Pointer simage = m_gelCorrelationAnalysis->getSImage();
	GelCorrelationAnalysis::DataImageType::Pointer dimage = m_gelCorrelationAnalysis->getDImage();
	GelCorrelationAnalysis::DataImageType::Pointer ptimage = m_gelCorrelationAnalysis->getPTImage();
	/*
	GelCorrelationAnalysis::DataImageType::SizeType roiSize;
	GelCorrelationAnalysis::DataImageType::IndexType roiIndex;
	double p1[3];
	double p2[3];
	m_rect->GetPoint(0, p1);
	m_rect->GetPoint(2, p2);

	roiSize[0] = abs(p2[0] - p1[0]);
	roiSize[1] = abs(p2[1] - p1[1]);

	//The index has to be the smallest in each case
	if(p1[0] < p2[0]) roiIndex[0] = p1[0] + 1;
	else roiIndex[0] = p2[0] + 1;

	if(p1[1] < p2[1]) roiIndex[1] = p1[1] + 1;
	else roiIndex[1] = p2[1] + 1;

	GelCorrelationAnalysis::DataImageType::RegionType roiDefinition;
	roiDefinition.SetIndex(roiIndex);
	roiDefinition.SetSize(roiSize);
	*/
	GelCorrelationAnalysis::DataImageType::RegionType roiDefinition;
	GetROIDefinition(&roiDefinition);

	GelCorrelationAnalysis::DataImageIteratorType roiIterC(cimage, roiDefinition);
	GelCorrelationAnalysis::DataImageIteratorType roiIterS(simage, roiDefinition);
	GelCorrelationAnalysis::DataImageIteratorType roiIterD(dimage, roiDefinition);
	GelCorrelationAnalysis::DataImageIteratorType roiIterPT(ptimage, roiDefinition);

	int npixelsToAnalyze = roiDefinition.GetNumberOfPixels();

	std::vector<float> *corrArray = new std::vector<float>(npixelsToAnalyze); 
	std::vector<float> *pArray = new std::vector<float>(npixelsToAnalyze);
	std::vector<float> *ptArray = new std::vector<float>(npixelsToAnalyze);

	roiIterC.GoToBegin();
	roiIterS.GoToBegin();
	roiIterD.GoToBegin();
	roiIterPT.GoToBegin();

	float maxCorr = -1;
	float maxAntiCorr = 1;

	GelCorrelationAnalysis::DataImageType::IndexType maxCorrIndex;
	GelCorrelationAnalysis::DataImageType::IndexType maxAcorrIndex;

	BOOL foundMaxC = FALSE;
	BOOL foundMaxAC = FALSE;
	double avgC = 0;
	double avgS = 0;
	double avgD = 0;
	double avgPT = 0;
	int nROIpixels = 0;
	int nInvalidPTpixels = 0;

	int i = 0;
	while(!roiIterC.IsAtEnd())
	{
		float cvalue = roiIterC.Get();
		float svalue = roiIterS.Get();
		float dvalue = roiIterD.Get();
		float ptvalue = roiIterPT.Get();

		avgC += cvalue;
		avgS += svalue;
		avgD += dvalue;
		if (ptvalue >= 0) 
		{
			avgPT += ptvalue;
			(*ptArray)[nROIpixels - nInvalidPTpixels] = ptvalue;
		}
		else nInvalidPTpixels++;

		(*corrArray)[nROIpixels] = cvalue;
		(*pArray)[nROIpixels] = 1 - svalue;

		nROIpixels++;
		if(cvalue > maxCorr)
		{
			maxCorr = cvalue;
			maxCorrIndex = roiIterC.GetIndex();
			foundMaxC = TRUE;
		}
		if(cvalue < maxAntiCorr)
		{
			maxAntiCorr = cvalue;
			maxAcorrIndex = roiIterC.GetIndex();
			foundMaxAC = TRUE;
		}
		++roiIterC;
		++roiIterS;
		++roiIterD;
		++roiIterPT;
	}
	avgC /= nROIpixels;
	avgS /= nROIpixels;
	avgD /= nROIpixels;
	int nPTpixels = nROIpixels - nInvalidPTpixels;
	if (nPTpixels > 0) avgPT /= nPTpixels;
	else avgPT = -1;

	float cmaxvalue;
	float smaxvalue;
	float dmaxvalue;
	float csmaxvalue;
	float csdmaxvalue;
	float cminvalue;
	float sminvalue;
	float dminvalue;
	float csminvalue;
	float csdminvalue;

	if(foundMaxC)
	{
		cmaxvalue = m_gelCorrelationAnalysis->getCImage()->GetPixel(maxCorrIndex);
		smaxvalue = m_gelCorrelationAnalysis->getSImage()->GetPixel(maxCorrIndex);
		dmaxvalue = m_gelCorrelationAnalysis->getDImage()->GetPixel(maxCorrIndex);
		csmaxvalue = m_gelCorrelationAnalysis->getCSImage()->GetPixel(maxCorrIndex);
		csdmaxvalue = m_gelCorrelationAnalysis->getCSDImage()->GetPixel(maxCorrIndex);
	}
	if(foundMaxAC)
	{
		cminvalue = m_gelCorrelationAnalysis->getCImage()->GetPixel(maxAcorrIndex);
		sminvalue = m_gelCorrelationAnalysis->getSImage()->GetPixel(maxAcorrIndex);
		dminvalue = m_gelCorrelationAnalysis->getDImage()->GetPixel(maxAcorrIndex);
		csminvalue = m_gelCorrelationAnalysis->getCSImage()->GetPixel(maxAcorrIndex);
		csdminvalue = m_gelCorrelationAnalysis->getCSDImage()->GetPixel(maxAcorrIndex);
	}

	//Now we know the max and min of the region.
	//We need to display it somehow.
	m_maxCorr = maxCorr;
	m_maxAntiCorr = maxAntiCorr;

	std::nth_element(corrArray->begin(), corrArray->begin() + (nROIpixels/2), corrArray->end());
	std::nth_element(pArray->begin(), pArray->begin() + (nROIpixels/2), pArray->end());
	float medC = corrArray->at(nROIpixels/2);
	float medP = pArray->at(nROIpixels/2);

	float medPT;
	if ((nROIpixels - nInvalidPTpixels) > 0)
	{
		std::nth_element(ptArray->begin(), ptArray->begin() + ((nROIpixels - nInvalidPTpixels)/2), ptArray->begin() + (nROIpixels - nInvalidPTpixels));
		medPT = ptArray->at((nROIpixels - nInvalidPTpixels)/2);
	}
	else medPT = -1;

	//Find coordinates.
	double p0[3];
	double p2[3];
	m_rect->GetPoint(0, p0);
	m_rect->GetPoint(2, p2);
	char string[500];
	if(foundMaxC)
	{
		sprintf_s(string, "ROI statistics (%.0f, %.0f) (%.0f, %.0f):\nMax/Min corr pixel:\nC: %.2f/%.2f P: %.2f/%.2f D: %.2f/%.2f\nAvg: C: %.3f P: %.3f PT: %.3f D: %.3f\nMed: C: %.3f P: %.3f PT: %.3f", 
			p0[0], p0[1], p2[0], p2[1], cmaxvalue, cminvalue, 1 - smaxvalue, 1 - sminvalue, dmaxvalue, dminvalue, avgC, 1 - avgS, avgPT, avgD, medC, medP, medPT);
	}
	else
	{
		sprintf_s(string, "ROI statistics:\nMax correlation:\nC: - S: - D: -\nMax anticorrelation:\nC: - S: - D: -", cmaxvalue, smaxvalue, dmaxvalue);
	}

	delete corrArray;
	m_ROITextActor->SetInput(string);
}


void ResultImageViewer::ListenToGelImageInteractor()
{
	vtkCallbackCommand * vtkCallbackCommand = vtkCallbackCommand::New();
	vtkCallbackCommand->SetCallback(gelImageUpdated);
	vtkCallbackCommand->SetClientData(this);

	m_gelImageViewer->GetInteractor()->AddObserver(vtkCommand::MouseMoveEvent, vtkCallbackCommand);
}

void ResultImageViewer::SetupMouseListener()
{
	vtkCallbackCommand *vtkCallbackCommand = vtkCallbackCommand::New();
	//Now we have something that can be called back.
	vtkCallbackCommand->SetCallback(mouseListener);
	vtkCallbackCommand->SetClientData(this);

	m_renderWindowInteractor->AddObserver(vtkCommand::MouseMoveEvent, vtkCallbackCommand);
	m_renderWindowInteractor->AddObserver(vtkCommand::LeftButtonPressEvent, vtkCallbackCommand);
	m_renderWindowInteractor->AddObserver(vtkCommand::LeftButtonReleaseEvent, vtkCallbackCommand);
	m_renderWindowInteractor->AddObserver(vtkCommand::RightButtonPressEvent, vtkCallbackCommand);
	m_renderWindowInteractor->AddObserver(vtkCommand::RightButtonReleaseEvent, vtkCallbackCommand);
}

void ResultImageViewer::SetColorTransferFunction(vtkColorTransferFunction *ctf) 
{
	m_ctf = ctf;
	m_colorBar->SetLookupTable(m_ctf);
	m_imageMapToColors->SetLookupTable(m_ctf);
	
}

void ResultImageViewer::ScreenDump()
{
	vtkJPEGWriter *writer = vtkJPEGWriter::New();
	vtkWindowToImageFilter *filter = vtkWindowToImageFilter::New();
	filter->SetInput(m_renderWindowInteractor->GetRenderWindow());
	writer->SetInputConnection(filter->GetOutputPort());
	filter->Modified();
	std::string name(m_baseFileName + "_result.jpg");
	writer->SetFileName(name.c_str());
	writer->Write();
	writer->Delete();
}

void ResultImageViewer::Load()
{
	m_Cconnector->SetInput(m_gelCorrelationAnalysis->getCImage());
	m_Sconnector->SetInput(m_gelCorrelationAnalysis->getSImage());
	m_Pconnector->SetInput(m_gelCorrelationAnalysis->getPImage());
	m_PTconnector->SetInput(m_gelCorrelationAnalysis->getPTImage());
	m_Dconnector->SetInput(m_gelCorrelationAnalysis->getDImage());
	m_CSconnector->SetInput(m_gelCorrelationAnalysis->getCSImage());
	m_CSDconnector->SetInput(m_gelCorrelationAnalysis->getCSDImage());
}	

void ResultImageViewer::Load(gel2de::File* aDirectory, std::string aIdString)
{
	gel2de::File thefile((*aDirectory), aIdString);
	m_baseFileName = thefile.path();

	m_Cconnector->SetInput(m_gelCorrelationAnalysis->getCImage());
	m_Sconnector->SetInput(m_gelCorrelationAnalysis->getSImage());
	m_Pconnector->SetInput(m_gelCorrelationAnalysis->getPImage());
	m_PTconnector->SetInput(m_gelCorrelationAnalysis->getPTImage());
	m_Dconnector->SetInput(m_gelCorrelationAnalysis->getDImage());
	m_CSconnector->SetInput(m_gelCorrelationAnalysis->getCSImage());
	m_CSDconnector->SetInput(m_gelCorrelationAnalysis->getCSDImage());
}

void ResultImageViewer::SetMetaInfo(std::string aParameterName, int aNumberOfGels, double aAverage)
{
	char string[200];
	sprintf_s(string, "Par = %s N = %d Avg = %.2f", aParameterName.c_str(), aNumberOfGels, aAverage);
	m_infoTextActor->SetInput(string);	
}
